#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <memory>
#include <functional>

#include <cstdio>
#include <cstring>
#include <cassert>
#include <cstdlib>

#include <unistd.h>
#include <pthread.h>
// 上下文
class Thread;
class Context
{
public:
    Thread *_this;
    void *_args;

public:
    Context() : _this(nullptr), _args(nullptr)
    {
    }

    ~Context()
    {
    }
};

class Thread
{
public:
    // 方法集合
    // typedef std::function<void *(void *)> func_t;

    // C++新方案
    using func_t = std::function<void *(void *)>;
    const int num = 128;

public:
    // 构造函数
    Thread(func_t func, void *args, int number) : _func(func), _args(args)
    {
        // C++方案
        // _name = "thread-";
        // _name += std::to_string(number);
        // C语言方案
        char buffer[num];
        snprintf(buffer, sizeof(buffer), "thread-%d", number);
        _name = buffer;
    }

    // void *start_routine(void *args  //类内成员，参数有缺省this指针
    // {
    //     return _func(args);
    // }

    // // 在类内创建线程，想要线程执行我们自定义的函数。需要将其设置为static，防止传入this参数
    // static void *start_routine(void *args) // 类内成员，参数有this指针
    // {
    //     return _func(args);
    // }

    // 由于静态方法只能调用静态成员变量和静态成员方法所以，我们不能直接_func(args)。这个不是静态成员
    static void *start_routine(void *args) // 类内静态成员，参数没有this指针
    {
        // 由于pthread_create会把ctx强制转化为void*  这里重新将ctx强制转化为Contest*
        Context *ctx = static_cast<Context *>(args);
        void *ret = ctx->_this->run(ctx->_args);
        delete ctx;
        return ret;
    }

    void start()
    {
        Context *ctx = new Context;
        ctx->_this = this;
        ctx->_args = _args;
        int n = pthread_create(&_tid, nullptr, start_routine, ctx);
        assert(n == 0); // 只存在于debug，在release不会使用
        (void)n;        // 在有些编译器上，release版本无assert。n没有被使用，会有warning
    }

    void join()
    {
        int n = pthread_join(_tid, nullptr);
        assert(n == 0);
        (void)n;
    }

    void *run(void *args)
    {
        return _func(args);
    }

    ~Thread()
    {
        // do nothing
    }

private:
    std::string _name; // 线程的名字
    pthread_t _tid;    // 线程的tid，即在虚拟内存线程TCB的起始地址
    func_t _func;      // 线程执行的方法
    void *_args;       // 线程方法的参数
};